/**
 * Copyright (c) 2021 OceanBase
 * OceanBase CE is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

%option noyywrap nounput noinput nodefault case-insensitive
%option noyyalloc noyyrealloc noyyfree
%option reentrant bison-bridge bison-locations
%option prefix="obsql_mysql_yy"
%option header-file="../../../src/sql/parser/sql_parser_mysql_mode_lex.h"
%{
#include "sql_parser_base.h"
#include "sql_parser_mysql_mode_tab.h"

extern void obsql_mysql_yyerror(YYLTYPE *yylloc, ParseResult *p, char *s,...);
extern void obsql_mysql_parser_fatal_error(yyconst char *msg, yyscan_t yyscanner);
#define yyerror obsql_mysql_yyerror
#define YY_FATAL_ERROR(msg) obsql_mysql_parser_fatal_error(msg , yyscanner)
%}

%x hint
%x in_c_comment
%x log_level
%x sq
%x dq
%x bt

U  [\x80-\xbf]
U_2  [\xc2-\xdf]
U_3  [\xe0-\xef]
U_4  [\xf0-\xf4]
GB_1 [\x81-\xfe]
GB_2 [\x40-\xfe]
GB_3 [\x30-\x39]
UTF8_GB_CHAR ({U_2}{U}|{U_3}{U}{U}|{U_4}{U}{U}{U}|{GB_1}{GB_2}|{GB_1}{GB_3}{GB_1}{GB_3})
space            [ \t\n\r\f]
non_newline      [^\n\r]
sql_comment      ("--"{space}+{non_newline}*)|(#{non_newline}*)
whitespace       ({space}+|{sql_comment})
select_hint_begin       (select{space}*(\/\*([^+*]|\*+[^*\/])*\*+\/{space}*)*(\/\*\+({space}*hint{space}+)?))
update_hint_begin       (update{space}*(\/\*([^+*]|\*+[^*\/])*\*+\/{space}*)*(\/\*\+({space}*hint{space}+)?))
delete_hint_begin       (delete{space}*(\/\*([^+*]|\*+[^*\/])*\*+\/{space}*)*(\/\*\+({space}*hint{space}+)?))
insert_hint_begin       (insert{space}*(\/\*([^+*]|\*+[^*\/])*\*+\/{space}*)*(\/\*\+({space}*hint{space}+)?))
replace_hint_begin      (replace{space}*(\/\*([^+*]|\*+[^*\/])*\*+\/{space}*)*(\/\*\+({space}*hint{space}+)?))
load_data_hint_begin    (load{space}+data{space}*(\/\*([^+*]|\*+[^*\/])*\*+\/{space}*)*(\/\*\+({space}*hint{space}+)?))
hint_hint_begin      (hint{space}*(\/\*([^+*]|\*+[^*\/])*\*+\/{space}*)*(\/\*\+({space}*hint{space}+)?))
common_hint_begin (\/\*\+({space}*hint{space}+)?)
c_cmt_begin      \/\*
c_cmt_end        \*+\/
comment          ({sql_comment})
identifier        (([A-Za-z0-9$_]|{UTF8_GB_CHAR})*)
log_level_stmt   ([A-Za-z][A-Za-z0-9_,\.:\* ]*)
system_variable  (@@[A-Za-z_][A-Za-z0-9_]*)
user_variable    (@[A-Za-z0-9_\.$]*)|(@[`'\"][`'\"A-Za-z0-9_\.$/%]*)
version_num      ([0-9]+\.+[0-9]*)
int_num          [0-9]+
client_version   \([0-9]+(\.[0-9]+)*\)

quote         '
sqbegin       {quote}
sqend         {quote}
sqdouble      {quote}{quote}
sqcontent     [^\\\n\r']+
qescape       [\\](.|\n)
sqnewline     {quote}{whitespace}{quote}

dquote         \"
dqbegin       {dquote}
dqend         {dquote}
dqdouble      {dquote}{dquote}
dqcontent     [^\\\n\r"]+
dqnewline     {dquote}{whitespace}{dquote}

backtick      `
btbegin       {backtick}
btend         {backtick}
btdouble      {backtick}{backtick}
btcontent     [^`]+

rowidPattern  (WITH{whitespace}ROWID)

%%
ACCESS                        { REPUT_TOKEN_NEG_SIGN(ACCESS); }
ACCESSIBLE                    { REPUT_TOKEN_NEG_SIGN(ACCESSIBLE); }
ADD                           { REPUT_TOKEN_NEG_SIGN(ADD); }
AGAINST                       { REPUT_TOKEN_NEG_SIGN(AGAINST); }
ALTER                         { REPUT_TOKEN_NEG_SIGN(ALTER); }
ALWAYS                        { REPUT_TOKEN_NEG_SIGN(ALWAYS); }
AND                           { REPUT_TOKEN_NEG_SIGN(AND); }
ALL                           { REPUT_TOKEN_NEG_SIGN(ALL); }
AS                            { REPUT_TOKEN_NEG_SIGN(AS); }
ASENSITIVE                    { REPUT_TOKEN_NEG_SIGN(ASENSITIVE); }
ASC                           { REPUT_TOKEN_NEG_SIGN(ASC); }
BETWEEN                       { REPUT_TOKEN_NEG_SIGN(BETWEEN); }
BEFORE                        { REPUT_TOKEN_NEG_SIGN(BEFORE); }
BIGINT                        { REPUT_TOKEN_NEG_SIGN(BIGINT); }
BINARY                        { REPUT_TOKEN_NEG_SIGN(BINARY); }
BLOB                          { REPUT_TOKEN_NEG_SIGN(BLOB); }
BOTH                          { REPUT_TOKEN_NEG_SIGN(BOTH); }
BY                            { REPUT_TOKEN_NEG_SIGN(BY); }
CALL                          { REPUT_TOKEN_NEG_SIGN(CALL); }
CASCADE                       { REPUT_TOKEN_NEG_SIGN(CASCADE); }
CASE                          { REPUT_TOKEN_NEG_SIGN(CASE); }
CHANGE                        { REPUT_TOKEN_NEG_SIGN(CHANGE); }
CHAR                          { REPUT_TOKEN_NEG_SIGN(CHARACTER); }
CHARACTER                     { REPUT_TOKEN_NEG_SIGN(CHARACTER); }
CHECK                         { REPUT_TOKEN_NEG_SIGN(CHECK); }
CIPHER                        { REPUT_TOKEN_NEG_SIGN(CIPHER); }
CONDITION                     { REPUT_TOKEN_NEG_SIGN(CONDITION); }
CONSTRAINT                    { REPUT_TOKEN_NEG_SIGN(CONSTRAINT); }
CONTINUE                      { REPUT_TOKEN_NEG_SIGN(CONTINUE); }
CONVERT                       { REPUT_TOKEN_NEG_SIGN(CONVERT); }
COLLATE                       { REPUT_TOKEN_NEG_SIGN(COLLATE); }
COLUMN                        { REPUT_TOKEN_NEG_SIGN(COLUMN); }
COLUMNS                       { REPUT_TOKEN_NEG_SIGN(COLUMNS); }
CREATE                        { REPUT_TOKEN_NEG_SIGN(CREATE); }
CROSS                         { REPUT_TOKEN_NEG_SIGN(CROSS); }
CYCLE                         { REPUT_TOKEN_NEG_SIGN(CYCLE); }
CURRENT_DATE                  { REPUT_TOKEN_NEG_SIGN(CURRENT_DATE); }
CURRENT_TIME                  { REPUT_TOKEN_NEG_SIGN(CURRENT_TIME); }
CURRENT_TIMESTAMP             { REPUT_TOKEN_NEG_SIGN(CURRENT_TIMESTAMP); }
CURRENT_USER                  { REPUT_TOKEN_NEG_SIGN(CURRENT_USER); }
{rowidPattern}                { REPUT_TOKEN_NEG_SIGN(WITH_ROWID); }
CURSOR                        { REPUT_TOKEN_NEG_SIGN(CURSOR); }
DAY_HOUR                      { REPUT_TOKEN_NEG_SIGN(DAY_HOUR); }
DAY_MICROSECOND               { REPUT_TOKEN_NEG_SIGN(DAY_MICROSECOND); }
DAY_MINUTE                    { REPUT_TOKEN_NEG_SIGN(DAY_MINUTE); }
DAY_SECOND                    { REPUT_TOKEN_NEG_SIGN(DAY_SECOND); }
DATABASE                      { REPUT_TOKEN_NEG_SIGN(DATABASE); }
DATABASES                     { REPUT_TOKEN_NEG_SIGN(DATABASES); }
DEC                           { REPUT_TOKEN_NEG_SIGN(NUMBER); }
DECIMAL                       { REPUT_TOKEN_NEG_SIGN(DECIMAL); }
DECLARE                       { REPUT_TOKEN_NEG_SIGN(DECLARE); }
DEFAULT                       { REPUT_TOKEN_NEG_SIGN(DEFAULT); }
DELAYED                       { REPUT_TOKEN_NEG_SIGN(DELAYED); }
DELETE                        { REPUT_TOKEN_NEG_SIGN(DELETE); }
DESC                          { REPUT_TOKEN_NEG_SIGN(DESC); }
DESCRIBE                      { REPUT_TOKEN_NEG_SIGN(DESCRIBE); }
DETERMINISTIC                 { REPUT_TOKEN_NEG_SIGN(DETERMINISTIC); }
DIV                           { REPUT_TOKEN_NEG_SIGN(DIV); }
DISTINCT                      { REPUT_TOKEN_NEG_SIGN(DISTINCT); }
DISTINCTROW                   { REPUT_TOKEN_NEG_SIGN(DISTINCTROW); }
DOUBLE                        { REPUT_TOKEN_NEG_SIGN(DOUBLE); }
DROP                          { REPUT_TOKEN_NEG_SIGN(DROP); }
DUAL                          { REPUT_TOKEN_NEG_SIGN(DUAL); }
EACH                          { REPUT_TOKEN_NEG_SIGN(EACH); }
ENCLOSED                      { REPUT_TOKEN_NEG_SIGN(ENCLOSED); }
ELSE                          { REPUT_TOKEN_NEG_SIGN(ELSE); }
ELSEIF                        { REPUT_TOKEN_NEG_SIGN(ELSEIF); }
ESCAPED                       { REPUT_TOKEN_NEG_SIGN(ESCAPED); }
EXISTS                        { REPUT_TOKEN_NEG_SIGN(EXISTS); }
EXIT                          { REPUT_TOKEN_NEG_SIGN(EXIT); }
EXPLAIN                       { REPUT_TOKEN_NEG_SIGN(EXPLAIN); }
FETCH                         { REPUT_TOKEN_NEG_SIGN(FETCH); }
FIELDS                        { REPUT_TOKEN_NEG_SIGN(FIELDS); }
FOREIGN                       { REPUT_TOKEN_NEG_SIGN(FOREIGN); }
FLOAT                         { REPUT_TOKEN_NEG_SIGN(FLOAT); }
FLOAT4                        { REPUT_TOKEN_NEG_SIGN(FLOAT4); }
FLOAT8                        { REPUT_TOKEN_NEG_SIGN(FLOAT8); }
FOR                           { REPUT_TOKEN_NEG_SIGN(FOR); }
FORCE                         { REPUT_TOKEN_NEG_SIGN(FORCE); }
FROM                          { REPUT_TOKEN_NEG_SIGN(FROM); }
FULL                          { REPUT_TOKEN_NEG_SIGN(FULL); }
GET                           { REPUT_TOKEN_NEG_SIGN(GET); }
GENERATED                     { REPUT_TOKEN_NEG_SIGN(GENERATED); }
GRANT                         { REPUT_TOKEN_NEG_SIGN(GRANT); }
GROUP                         { REPUT_TOKEN_NEG_SIGN(GROUP); }
HAVING                        { REPUT_TOKEN_NEG_SIGN(HAVING); }
HIGH_PRIORITY                 { REPUT_TOKEN_NEG_SIGN(HIGH_PRIORITY); }
HOUR_MICROSECOND              { REPUT_TOKEN_NEG_SIGN(HOUR_MICROSECOND); }
HOUR_MINUTE                   { REPUT_TOKEN_NEG_SIGN(HOUR_MINUTE); }
HOUR_SECOND                   { REPUT_TOKEN_NEG_SIGN(HOUR_SECOND); }
ID                            { REPUT_TOKEN_NEG_SIGN(ID); }
IF                            { REPUT_TOKEN_NEG_SIGN(IF); }
IN                            { REPUT_TOKEN_NEG_SIGN(IN); }
INDEX                         { REPUT_TOKEN_NEG_SIGN(INDEX); }
INNER                         { REPUT_TOKEN_NEG_SIGN(INNER); }
INFILE                        { REPUT_TOKEN_NEG_SIGN(INFILE); }
INOUT                         { REPUT_TOKEN_NEG_SIGN(INOUT); }
INSENSITIVE                   { REPUT_TOKEN_NEG_SIGN(INSENSITIVE); }
INT                           { REPUT_TOKEN_NEG_SIGN(INTEGER); }
INT1                          { REPUT_TOKEN_NEG_SIGN(INT1); }
INT2                          { REPUT_TOKEN_NEG_SIGN(INT2); }
INT3                          { REPUT_TOKEN_NEG_SIGN(INT3); }
INT4                          { REPUT_TOKEN_NEG_SIGN(INT4); }
INT8                          { REPUT_TOKEN_NEG_SIGN(INT8); }
INTEGER                       { REPUT_TOKEN_NEG_SIGN(INTEGER); }
INTERVAL { 
  ParseResult *p = (ParseResult *)yyextra;
  REPUT_NEG_SIGN(p); 
  return INTERVAL; 
}
INSERT                        { REPUT_TOKEN_NEG_SIGN(INSERT); }
INTO                          { REPUT_TOKEN_NEG_SIGN(INTO); }
IO_AFTER_GTIDS                { REPUT_TOKEN_NEG_SIGN(IO_AFTER_GTIDS); }
IO_BEFORE_GTIDS               { REPUT_TOKEN_NEG_SIGN(IO_BEFORE_GTIDS); }
IS                            { REPUT_TOKEN_NEG_SIGN(IS); }
ISSUER                        { REPUT_TOKEN_NEG_SIGN(ISSUER); }
ITERATE                       { REPUT_TOKEN_NEG_SIGN(ITERATE); }
JOIN                          { REPUT_TOKEN_NEG_SIGN(JOIN); }
KEY                           { REPUT_TOKEN_NEG_SIGN(KEY); }
KEYS                          { REPUT_TOKEN_NEG_SIGN(KEYS); }
KILL                          { REPUT_TOKEN_NEG_SIGN(KILL); }
LANGUAGE                      { REPUT_TOKEN_NEG_SIGN(LANGUAGE); }
LEADING                       { REPUT_TOKEN_NEG_SIGN(LEADING); }
LEAVE                         { REPUT_TOKEN_NEG_SIGN(LEAVE); }
LEFT                          { REPUT_TOKEN_NEG_SIGN(LEFT); }
LIMIT                         { REPUT_TOKEN_NEG_SIGN(LIMIT); }
LIKE                          { REPUT_TOKEN_NEG_SIGN(LIKE); }
LINEAR                        { REPUT_TOKEN_NEG_SIGN(LINEAR); }
LINES                         { REPUT_TOKEN_NEG_SIGN(LINES); }
LIST                          { REPUT_TOKEN_NEG_SIGN(BISON_LIST); }
LOAD                          { REPUT_TOKEN_NEG_SIGN(LOAD); }
LOCAL                         { REPUT_TOKEN_NEG_SIGN(LOCAL); }
LOCALTIME                     { REPUT_TOKEN_NEG_SIGN(LOCALTIME); }
LOCALTIMESTAMP                { REPUT_TOKEN_NEG_SIGN(LOCALTIMESTAMP); }
LOCK                          { REPUT_TOKEN_NEG_SIGN(LOCK_); }
LONG                          { REPUT_TOKEN_NEG_SIGN(LONG); }
LONGBLOB                      { REPUT_TOKEN_NEG_SIGN(LONGBLOB); }
LONGTEXT                      { REPUT_TOKEN_NEG_SIGN(LONGTEXT); }
LOOP                          { REPUT_TOKEN_NEG_SIGN(LOOP); }
LOW_PRIORITY                  { REPUT_TOKEN_NEG_SIGN(LOW_PRIORITY); }
MASTER_BIND                   { REPUT_TOKEN_NEG_SIGN(MASTER_BIND); }
MASTER_SSL_VERIFY_SERVER_CERT { REPUT_TOKEN_NEG_SIGN(MASTER_SSL_VERIFY_SERVER_CERT); }
MATCH                         { REPUT_TOKEN_NEG_SIGN(MATCH); }
MAXVALUE                      { REPUT_TOKEN_NEG_SIGN(MAXVALUE); }
MEDIUMBLOB                    { REPUT_TOKEN_NEG_SIGN(MEDIUMBLOB); }
MEDIUMINT                     { REPUT_TOKEN_NEG_SIGN(MEDIUMINT); }
MERGE                         { REPUT_TOKEN_NEG_SIGN(MERGE); }
MEDIUMTEXT                    { REPUT_TOKEN_NEG_SIGN(MEDIUMTEXT); }
MIDDLEINT                     { REPUT_TOKEN_NEG_SIGN(MIDDLEINT); }
MINUTE_MICROSECOND            { REPUT_TOKEN_NEG_SIGN(MINUTE_MICROSECOND); }
MINUTE_SECOND                 { REPUT_TOKEN_NEG_SIGN(MINUTE_SECOND); }
MOD                           { REPUT_TOKEN_NEG_SIGN(MOD); }
MODE                          { REPUT_TOKEN_NEG_SIGN(MODE); }
MODIFIES                      { REPUT_TOKEN_NEG_SIGN(MODIFIES); }
NATURAL                       { REPUT_TOKEN_NEG_SIGN(NATURAL); }
NO_WRITE_TO_BINLOG            { REPUT_TOKEN_NEG_SIGN(NO_WRITE_TO_BINLOG); }
NUMERIC                       { REPUT_TOKEN_NEG_SIGN(NUMBER); }
ON                            { REPUT_TOKEN_NEG_SIGN(ON); }
OPTION                        { REPUT_TOKEN_NEG_SIGN(OPTION); }
OPTIMIZE                      { REPUT_TOKEN_NEG_SIGN(OPTIMIZE); }
OPTIONALLY                    { REPUT_TOKEN_NEG_SIGN(OPTIONALLY); }
OR                            { REPUT_TOKEN_NEG_SIGN(OR); }
ORDER                         { REPUT_TOKEN_NEG_SIGN(ORDER); }
OUT                           { REPUT_TOKEN_NEG_SIGN(OUT); }
OUTER                         { REPUT_TOKEN_NEG_SIGN(OUTER); }
OUTFILE                       { REPUT_TOKEN_NEG_SIGN(OUTFILE); }
PARSER                        { REPUT_TOKEN_NEG_SIGN(PARSER); }
PROCEDURE                     { REPUT_TOKEN_NEG_SIGN(PROCEDURE); }
PURGE                         { REPUT_TOKEN_NEG_SIGN(PURGE); }
PARTITION                     { REPUT_TOKEN_NEG_SIGN(PARTITION); }
PRECISION                     { REPUT_TOKEN_NEG_SIGN(PRECISION); }
PRIMARY                       { REPUT_TOKEN_NEG_SIGN(PRIMARY); }
PUBLIC                        { REPUT_TOKEN_NEG_SIGN(PUBLIC); }
RANGE                         { REPUT_TOKEN_NEG_SIGN(RANGE); }
READ                          { REPUT_TOKEN_NEG_SIGN(READ); }
READ_WRITE                    { REPUT_TOKEN_NEG_SIGN(READ_WRITE); }
READS                         { REPUT_TOKEN_NEG_SIGN(READS); }
REAL                          { REPUT_TOKEN_NEG_SIGN(REAL); }
RELEASE                       { REPUT_TOKEN_NEG_SIGN(RELEASE); }
REFERENCES                    { REPUT_TOKEN_NEG_SIGN(REFERENCES); }
REGEXP                        { REPUT_TOKEN_NEG_SIGN(REGEXP); }
RENAME                        { REPUT_TOKEN_NEG_SIGN(RENAME); }
REPLACE                       { REPUT_TOKEN_NEG_SIGN(REPLACE); }
REPEAT                        { REPUT_TOKEN_NEG_SIGN(REPEAT); }
REQUIRE                       { REPUT_TOKEN_NEG_SIGN(REQUIRE); }
RESIGNAL                      { REPUT_TOKEN_NEG_SIGN(RESIGNAL); }
RESTRICT                      { REPUT_TOKEN_NEG_SIGN(RESTRICT); }
RETURN                        { REPUT_TOKEN_NEG_SIGN(RETURN); }
REVOKE                        { REPUT_TOKEN_NEG_SIGN(REVOKE); }
RIGHT                         { REPUT_TOKEN_NEG_SIGN(RIGHT); }
RLIKE                         { REPUT_TOKEN_NEG_SIGN(REGEXP); }
ROWS                          { REPUT_TOKEN_NEG_SIGN(ROWS); }
SECOND_MICROSECOND            { REPUT_TOKEN_NEG_SIGN(SECOND_MICROSECOND); }
SELECT                        { REPUT_TOKEN_NEG_SIGN(SELECT); }
SCHEMA                        { REPUT_TOKEN_NEG_SIGN(SCHEMA); }
SCHEMAS                       { REPUT_TOKEN_NEG_SIGN(SCHEMAS); }
SEPARATOR                     { REPUT_TOKEN_NEG_SIGN(SEPARATOR); }
SET                           { REPUT_TOKEN_NEG_SIGN(SET); }
SENSITIVE                     { REPUT_TOKEN_NEG_SIGN(SENSITIVE); }
SHOW                          { REPUT_TOKEN_NEG_SIGN(SHOW); }
SIGNAL                        { REPUT_TOKEN_NEG_SIGN(SIGNAL); }
SMALLINT                      { REPUT_TOKEN_NEG_SIGN(SMALLINT); }
SPATIAL                       { REPUT_TOKEN_NEG_SIGN(SPATIAL); }
SPECIFIC                      { REPUT_TOKEN_NEG_SIGN(SPECIFIC); }
SQL                           { REPUT_TOKEN_NEG_SIGN(SQL); }
SQLEXCEPTION                  { REPUT_TOKEN_NEG_SIGN(SQLEXCEPTION); }
SQLSTATE                      { REPUT_TOKEN_NEG_SIGN(SQLSTATE); }
SQLWARNING                    { REPUT_TOKEN_NEG_SIGN(SQLWARNING); }
SQL_BIG_RESULT                { REPUT_TOKEN_NEG_SIGN(SQL_BIG_RESULT); }
SQL_CALC_FOUND_ROWS           { REPUT_TOKEN_NEG_SIGN(SQL_CALC_FOUND_ROWS); }
SQL_SMALL_RESULT              { REPUT_TOKEN_NEG_SIGN(SQL_SMALL_RESULT); }
SSL                           { REPUT_TOKEN_NEG_SIGN(SSL); }
STARTING                      { REPUT_TOKEN_NEG_SIGN(STARTING); }
STORED                        { REPUT_TOKEN_NEG_SIGN(STORED); }
STRAIGHT_JOIN                 { REPUT_TOKEN_NEG_SIGN(STRAIGHT_JOIN); }
SUBJECT                       { REPUT_TOKEN_NEG_SIGN(SUBJECT); }
SYNONYM                       { REPUT_TOKEN_NEG_SIGN(SYNONYM); }
SYSDATE                       { REPUT_TOKEN_NEG_SIGN(SYSDATE); }
TERMINATED                    { REPUT_TOKEN_NEG_SIGN(TERMINATED); }
TEXT                          { REPUT_TOKEN_NEG_SIGN(TEXT); }
TINYBLOB                      { REPUT_TOKEN_NEG_SIGN(TINYBLOB); }
TINYINT                       { REPUT_TOKEN_NEG_SIGN(TINYINT); }
TINYTEXT                      { REPUT_TOKEN_NEG_SIGN(TINYTEXT); }
TABLE                         { REPUT_TOKEN_NEG_SIGN(TABLE); }
TABLEGROUP                    { REPUT_TOKEN_NEG_SIGN(TABLEGROUP); }
THEN                          { REPUT_TOKEN_NEG_SIGN(THEN); }
TO                            { REPUT_TOKEN_NEG_SIGN(TO); }
TRAILING                      { REPUT_TOKEN_NEG_SIGN(TRAILING); }
TRIGGER                       { REPUT_TOKEN_NEG_SIGN(TRIGGER); }
UNDO                          { REPUT_TOKEN_NEG_SIGN(UNDO); }
UNION                         { REPUT_TOKEN_NEG_SIGN(UNION); }
UNIQUE                        { REPUT_TOKEN_NEG_SIGN(UNIQUE); }
UNLOCK                        { REPUT_TOKEN_NEG_SIGN(UNLOCK); }
UNSIGNED                      { REPUT_TOKEN_NEG_SIGN(UNSIGNED); }
UPDATE                        { REPUT_TOKEN_NEG_SIGN(UPDATE); }
USAGE                         { REPUT_TOKEN_NEG_SIGN(USAGE); }
USE                           { REPUT_TOKEN_NEG_SIGN(USE); }
USING                         { REPUT_TOKEN_NEG_SIGN(USING); }
UTC_DATE                      { REPUT_TOKEN_NEG_SIGN(UTC_DATE); }
UTC_TIME                      { REPUT_TOKEN_NEG_SIGN(UTC_TIME); }
UTC_TIMESTAMP                 { REPUT_TOKEN_NEG_SIGN(UTC_TIMESTAMP); }
VALUES                        { REPUT_TOKEN_NEG_SIGN(VALUES); }
VARBINARY                     { REPUT_TOKEN_NEG_SIGN(VARBINARY); }
VARCHAR                       { REPUT_TOKEN_NEG_SIGN(VARCHAR); }
VARCHARACTER                  { REPUT_TOKEN_NEG_SIGN(VARCHAR); }
VARYING                       { REPUT_TOKEN_NEG_SIGN(VARYING); }
VIRTUAL                       { REPUT_TOKEN_NEG_SIGN(VIRTUAL); }
WHERE                         { REPUT_TOKEN_NEG_SIGN(WHERE); }
WHEN                          { REPUT_TOKEN_NEG_SIGN(WHEN); }
WHILE                         { REPUT_TOKEN_NEG_SIGN(WHILE); }
WINDOW                        { REPUT_TOKEN_NEG_SIGN(WINDOW); }
WITH                          { REPUT_TOKEN_NEG_SIGN(WITH); }
WRITE                         { REPUT_TOKEN_NEG_SIGN(WRITE); }
XOR                           { REPUT_TOKEN_NEG_SIGN(XOR); }
X509                          { REPUT_TOKEN_NEG_SIGN(X509); }
YEAR_MONTH                    { REPUT_TOKEN_NEG_SIGN(YEAR_MONTH); }
ZEROFILL                      { REPUT_TOKEN_NEG_SIGN(ZEROFILL); }
@@global                      { REPUT_TOKEN_NEG_SIGN(GLOBAL_ALIAS); }
@@session                     { REPUT_TOKEN_NEG_SIGN(SESSION_ALIAS); }
@@local                       { REPUT_TOKEN_NEG_SIGN(SESSION_ALIAS); }

_UTF8                         { REPUT_TOKEN_NEG_SIGN(_UTF8); }
_UTF8MB4                      { REPUT_TOKEN_NEG_SIGN(_UTF8MB4); }
_GBK                          { REPUT_TOKEN_NEG_SIGN(_GBK); }
_GB18030                      { REPUT_TOKEN_NEG_SIGN(_GB18030); }
_BINARY                       { REPUT_TOKEN_NEG_SIGN(_BINARY); }
_UTF16                        { REPUT_TOKEN_NEG_SIGN(_UTF16); }
STRONG                        { REPUT_TOKEN_NEG_SIGN(STRONG); }
WEAK                          { REPUT_TOKEN_NEG_SIGN(WEAK); }
FROZEN                        { REPUT_TOKEN_NEG_SIGN(FROZEN); }
EXCEPT                        { REPUT_TOKEN_NEG_SIGN(EXCEPT); }
MINUS                         { REPUT_TOKEN_NEG_SIGN(MINUS); }
INTERSECT                     { REPUT_TOKEN_NEG_SIGN(INTERSECT); }
ISNULL                        { REPUT_TOKEN_NEG_SIGN(ISNULL); }
NOT {
  int32_t token_ret = NOT; /*fast parameterize don't care NOT or NOT2*/
  if (!(IS_FAST_PARAMETERIZE)) {
    ObSQLMode mode = ((ParseResult *)yyextra)->sql_mode_;
    bool is_high_not_procedence = false;
      IS_HIGH_NOT_PRECEDENCE(mode, is_high_not_procedence);
    if (is_high_not_procedence) {
      token_ret = NOT2;
    } else {
      token_ret = NOT;
    }
  }
  return token_ret;
}
NULL {
  check_value(yylval);
  ParseResult *p = (ParseResult *)yyextra;
  malloc_new_node(yylval->node, p->malloc_pool_, T_NULL, 0);
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return NULLX;
  }
}

{int_num} {
  int32_t token_ret = INTNUM;
  ParseNode *node = NULL;
  check_value(yylval);
  ParseResult *p = (ParseResult *)yyextra;
  malloc_new_node(node, p->malloc_pool_, T_INT, 0);
  yylval->node = node;
  int err_no = 0;
  COPY_NUM_STRING(p, node);
  // we treated '-  12' as a const node, that is to say node->str_value_ = '-  12'
  // however `strtoll` can't parse '-  12' to a int value, for there are spaces between neg sign and numbers
  // so here, we have to strip spaces
  PARSE_INT_STR_MYSQL(node, p->malloc_pool_, err_no);
  node->raw_text_ = node->str_value_;
  node->text_len_ = node->str_len_;
  p->minus_ctx_.is_cur_numeric_ = true;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    setup_token_pos_info(node, yylloc->first_column - 1, node->text_len_);
    return token_ret;
  }
}

<hint>{int_num} {
  ParseResult *p = (ParseResult *)yyextra;
  if (!p->is_ignore_token_) {
    if (IS_FAST_PARAMETERIZE) {
      COPY_WRITE();
    } else {
      int32_t token_ret = INTNUM;
      ParseNode *node = NULL;
      ParseResult *p = (ParseResult *)yyextra;
      malloc_new_node(node, p->malloc_pool_, T_INT, 0);
      check_value(yylval);
      yylval->node = node;
      node->str_value_ = parse_strdup(yytext, p->malloc_pool_, &(node->str_len_));
      check_value(node->str_value_);
      int err_no = 0;
      node->value_ = ob_strntoll(node->str_value_, node->str_len_, 10, NULL, &err_no);
      if (ERANGE == err_no)
      {
        /* if out of range, seem it as must NUMERIC type, now is double */
        node->type_ = T_NUMBER;
        token_ret = DECIMAL_VAL;
      }
      return token_ret;
    }
  }
}

[0-9]+E[-+]?[0-9]+ |
[0-9]+"."[0-9]*E[-+]?[0-9]+ |
"."[0-9]+E[-+]?[0-9]+ {
  ParseNode *node = NULL;
  ParseResult *p = (ParseResult *)yyextra;
  malloc_new_node(node, p->malloc_pool_, T_DOUBLE, 0);
  check_value(yylval);
  yylval->node = node;
  COPY_NUM_STRING(p, node);
  node->raw_text_ = node->str_value_;
  node->text_len_ = node->str_len_;
  p->minus_ctx_.is_cur_numeric_ = true;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return DECIMAL_VAL;
  }
}

[0-9]+"."[0-9]* |
"."[0-9]+ {
  ParseNode *node = NULL;
  ParseResult *p = (ParseResult *)yyextra;
  malloc_new_node(node, p->malloc_pool_, T_NUMBER/* should be T_NUMBER,*/, 0);
  check_value(yylval);
  yylval->node = node;
  COPY_NUM_STRING(p, node);
  node->raw_text_ = node->str_value_;
  node->text_len_ = node->str_len_;
  p->minus_ctx_.is_cur_numeric_ = true;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return DECIMAL_VAL;
  }
}

TRUE {
  check_value(yylval);
  ParseResult *p = (ParseResult *)yyextra;
  malloc_new_node(yylval->node, p->malloc_pool_, T_BOOL, 0);
  yylval->node->value_ = 1;
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return BOOL_VALUE;
  }
}

FALSE {
  check_value(yylval);
  ParseResult *p = (ParseResult *)yyextra;
  malloc_new_node(yylval->node, p->malloc_pool_, T_BOOL, 0);
  yylval->node->value_ = 0;
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return BOOL_VALUE;
  }
}

{sqbegin} {
  BEGIN(sq);
  ParseResult *p = (ParseResult *)yyextra;
  p->start_col_ = yylloc->first_column;
  check_value(yylval);
  malloc_new_node(yylval->node, p->malloc_pool_, T_VARCHAR, 0);
  yylval->node->str_len_ = 0;
  p->last_well_formed_len_ = 0;
  yylval->node->str_value_ = NULL;
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    COPY_WRITE();
  }
}

<sq>{sqend} { // fast parameterize copy text here, don't return token
  BEGIN(INITIAL);
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  yylloc->first_column = p->start_col_;
  FORMAT_STR_NODE(yylval->node);
  yylval->node->text_len_ = yylloc->last_column - p->start_col_ + 1;
  COPY_STRING(p->input_sql_ + p->start_col_ - 1, yylval->node->text_len_, yylval->node->raw_text_);
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    setup_token_pos_info(yylval->node, yylloc->first_column, yylval->node->text_len_ - 2);
    return STRING_VALUE;
  }
}

<sq>{sqdouble} {
  check_value(yylval);
  COPY_STR_NODE_TO_TMP_LITERAL(yylval->node);
  ((ParseResult *)yyextra)->tmp_literal_[yylval->node->str_len_++] = '\'';
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    COPY_WRITE();
  }
}

<sq>{sqcontent} {
  check_value(yylval);
  STORE_STR_CONTENT(yylval->node);
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    COPY_WRITE();
  }
}

<sq>[\n\r] {
  check_value(yylval);
  ++yylineno;
  STORE_STR_CONTENT(yylval->node);
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    COPY_WRITE();
  }
}

<sq>{qescape} {
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  COPY_STR_NODE_TO_TMP_LITERAL(yylval->node);
  bool is_real_escape = true;
  CHECK_REAL_ESCAPE(is_real_escape);
  if (!is_real_escape) {
    HANDLE_FALSE_ESCAPE(p);
  } else {
    HANDLE_ESCAPE(p);
  }
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    COPY_WRITE();
  }
}

<sq>{sqnewline} {
  /*TODO fast parameterize*/
  /*
     In case of two adjacent string literal, such as " 'a' 'b' ", the two string will be
     concatenate into 'ab'. However, the string 'a' will used as the column name if it appears
     in the select list, which means we must save it rather than just skipping the 'sqnewline'.

     One solution is to do this in the yacc and let the lexer produce all strings as individual
     tokens. However, it will generate ambiguity in the yacc according to our grammar definition.
     Instead, we remember the first string as a child of the 'T_VARCHAR' node which represents
     " 'a' 'b' ", whose str_value_ is 'ab'. This will save us from modifying our grammar and a
     a lot of troubles.
   */
  check_value(yylval);
  ADD_YYLINENO(yytext, yyleng);
  COPY_STR_NODE_TO_TMP_LITERAL(yylval->node);
  if (0 == yylval->node->num_child_) {
    ParseResult *p = (ParseResult *)yyextra;
    char *tmp_literal = p->tmp_literal_;
    tmp_literal[yylval->node->str_len_] = '\0';
    yylval->node->children_ = (ParseNode **)parse_malloc(sizeof(ParseNode *), p->malloc_pool_);
    if (OB_UNLIKELY(NULL == yylval->node->children_)) {
      p->extra_errno_ = OB_PARSER_ERR_NO_MEMORY;
      yyerror(yylloc, yyextra, "No more space for mallocing '%s'\n", yytext);
      return ERROR;
    }

    malloc_new_node(yylval->node->children_[0], p->malloc_pool_, T_CONCAT_STRING, 0);
    (*yylval->node->children_)->str_value_ = parse_strndup(tmp_literal, yylval->node->str_len_ + 1,
                                            p->malloc_pool_);
    (*yylval->node->children_)->str_len_ = yylval->node->str_len_;
    yylval->node->num_child_ = 1;
  }
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    COPY_WRITE();
  }
}

<sq><<EOF>>  {
  yyerror(yylloc, yyextra, "unterminated quoted string\n");
  return PARSER_SYNTAX_ERROR;
}

{dqbegin} {
  BEGIN(dq);
  ParseResult *p = (ParseResult *)yyextra;
  p->start_col_ = yylloc->first_column;
  char **tmp_literal = &p->tmp_literal_;
  if (*tmp_literal == NULL)
  {
    *tmp_literal = (char*) parse_malloc(p->input_sql_len_ + 1, p->malloc_pool_);
    check_value(*tmp_literal);
  }
  malloc_new_node(yylval->node, p->malloc_pool_, T_VARCHAR, 0);
  yylval->node->str_len_ = 0;
  p->last_well_formed_len_ = 0;
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    return OUTLINE_DEFAULT_TOKEN;
  }
}

<dq>{dqend} {
  BEGIN(INITIAL);
  ParseResult *p = (ParseResult *)yyextra;
  yylloc->first_column = p->start_col_;
  char *tmp_literal = p->tmp_literal_;
  check_value(yylval);
  tmp_literal[yylval->node->str_len_] = '\0';
  yylval->node->str_value_ = parse_strndup(tmp_literal, yylval->node->str_len_ + 1, p->malloc_pool_);
  yylval->node->text_len_ = yylloc->last_column - p->start_col_ + 1;
  yylval->node->raw_text_ = parse_strndup(p->input_sql_ + p->start_col_ - 1, yylval->node->text_len_, p->malloc_pool_);
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    setup_token_pos_info(yylval->node, yylloc->first_column, yylval->node->str_len_);
    return STRING_VALUE;
  }
}

<dq>{dqdouble} {
  check_value(yylval);
  ((ParseResult *)yyextra)->tmp_literal_[yylval->node->str_len_++] = '\"';
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    return OUTLINE_DEFAULT_TOKEN;
  }
}

<dq>{dqcontent} {
  check_value(yylval);
  memmove(((ParseResult *)yyextra)->tmp_literal_ + yylval->node->str_len_, yytext, yyleng);
  yylval->node->str_len_ += yyleng;
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    return OUTLINE_DEFAULT_TOKEN;
  }
}

<dq>[\n\r] {
  check_value(yylval);
  ++yylineno;
  memmove(((ParseResult *)yyextra)->tmp_literal_ + yylval->node->str_len_, yytext, yyleng);
  yylval->node->str_len_ += yyleng;
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    return OUTLINE_DEFAULT_TOKEN;
  }
}

<dq>{qescape} {
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  bool is_real_escape = true;
  CHECK_REAL_ESCAPE(is_real_escape);
  if (!is_real_escape) {
    HANDLE_FALSE_ESCAPE(p);
  } else {
    HANDLE_ESCAPE(p);
  }
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    return OUTLINE_DEFAULT_TOKEN;
  }
}


<dq>{dqnewline} {
  /* see 'sqnewline' */
  check_value(yylval);
  ADD_YYLINENO(yytext, yyleng);
  if (0 == yylval->node->num_child_) {
    ParseResult *p = (ParseResult *)yyextra;
    char *tmp_literal = p->tmp_literal_;
    tmp_literal[yylval->node->str_len_] = '\0';

    yylval->node->children_ = (ParseNode **)parse_malloc(sizeof(ParseNode *), p->malloc_pool_);
    if (OB_UNLIKELY(NULL == yylval->node->children_)) {
      p->extra_errno_ = OB_PARSER_ERR_NO_MEMORY;
      yyerror(yylloc, yyextra, "No more space for mallocing '%s'\n", yytext);
      return ERROR;
    }

    malloc_new_node(yylval->node->children_[0], p->malloc_pool_, T_CONCAT_STRING, 0);
    (*yylval->node->children_)->str_value_ = parse_strndup(tmp_literal, yylval->node->str_len_ + 1,
                                            p->malloc_pool_);
    (*yylval->node->children_)->str_len_ = yylval->node->str_len_;
    yylval->node->num_child_ = 1;
  }
  if (IS_FAST_PARAMETERIZE && !IS_NEED_PARAMETERIZE) {
    return OUTLINE_DEFAULT_TOKEN;
  }
}

<dq><<EOF>>  {
  yyerror(yylloc, yyextra, "unterminated doublequoted string\n");
  return PARSER_SYNTAX_ERROR;
}

{btbegin} {
  BEGIN(bt); /*fast parameterize don't handle connent in ``*/
  if (IS_FAST_PARAMETERIZE) {
    COPY_WRITE();
  } else {
    check_value(yylval);
    ParseResult *p = (ParseResult *)yyextra;
    p->start_col_ = yylloc->first_column;
    char **tmp_literal = &p->tmp_literal_;
    if (NULL == *tmp_literal)
    {
      *tmp_literal = (char *)parse_malloc(p->input_sql_len_ + 1, p->malloc_pool_);
      check_value(*tmp_literal);
    }
    malloc_new_node(yylval->node, p->malloc_pool_, T_IDENT, 0);
    yylval->node->str_len_ = 0;
  }
}

<bt>{btdouble} {
  if (IS_FAST_PARAMETERIZE) {
    COPY_WRITE();
  } else {
    check_value(yylval);
    ((ParseResult *)yyextra)->tmp_literal_[yylval->node->str_len_++] = '`';
  }
}
<bt>{btcontent} {
  if (IS_FAST_PARAMETERIZE) {
    COPY_WRITE();
  } else {
    check_value(yylval);
    memmove(((ParseResult *)yyextra)->tmp_literal_ + yylval->node->str_len_, yytext, yyleng);
    yylval->node->str_len_ += yyleng;
  }
}

<bt>{btend} {
  BEGIN(INITIAL);
  if (IS_FAST_PARAMETERIZE) {
    COPY_WRITE();
  } else {
    ParseResult *p = (ParseResult *)yyextra;
    check_value(yylval);
    yylloc->first_column = p->start_col_;
    char *tmp_literal = p->tmp_literal_;
    tmp_literal[yylval->node->str_len_] = '\0';

    char *dup_value = NULL;
    if (p->is_not_utf8_connection_) {
      dup_value = parse_str_convert_utf8(p->charset_info_, tmp_literal, p->malloc_pool_, &(yylval->node->str_len_), &(p->extra_errno_));
      check_identifier_convert_result(p->extra_errno_);
      //fprintf(stderr, "parse identifier result, str=%s, str_len=%ld\n", node->str_value_, node->str_len_);
    } else {
      dup_value = parse_strndup(tmp_literal, yylval->node->str_len_ + 1, p->malloc_pool_);
    }
    check_value(dup_value);
    yylval->node->str_value_ = dup_value;
    setup_token_pos_info(yylval->node, yylloc->first_column, yylval->node->str_len_);
    return NAME_OB;
  }
}

<bt><<EOF>>  {
  yyerror(yylloc, yyextra, "unterminated backtick string\n");
  return PARSER_SYNTAX_ERROR;
}

X'([0-9A-F])*'|0X([0-9A-F])+ {
  char *src = yytext + 2;
  size_t len = yyleng - 2;
  if ('\'' == src[len - 1]) {
    --len;
  }
  ParseNode *node = NULL;
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  malloc_new_node(node, p->malloc_pool_, T_HEX_STRING, 0);
  if (len > 0) {
    int64_t dest_len = ob_parse_binary_len(len);
    char *dest = (char *)parse_malloc(dest_len, p->malloc_pool_);
    check_value(dest);
    ob_parse_binary(src, len, dest);
    node->str_value_ = dest;
    node->str_len_ = dest_len;
  }
  else
  {
    node->str_value_ = NULL;
    node->str_len_ = 0;
  }
  yylval->node = node;
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  yylval->node->is_copy_raw_text_ = 1;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return HEX_STRING_VALUE;
  }
}

B'([01])*'|0B([01])+ {
  char* src = yytext + 2;
  size_t len = yyleng - 2;
  if(src[len - 1] == '\'')
  {
    --len;
  }
  ParseNode *node = NULL;
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  malloc_new_node(node, p->malloc_pool_, T_HEX_STRING, 0);
  if (len > 0)
  {
    int64_t dest_len = ob_parse_bit_string_len(len);
    char *dest = (char*)parse_malloc(dest_len, p->malloc_pool_);
    check_value(dest);
    ob_parse_bit_string(src, len, dest);
    node->str_value_ = dest;
    node->str_len_ = dest_len;
  }
  else
  {
    node->str_value_ = NULL;
    node->str_len_ = 0;
  }
  yylval->node = node;
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  yylval->node->is_copy_raw_text_ = 1;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return HEX_STRING_VALUE;
  }
}

Date{whitespace}?'[^']*' {
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  malloc_time_node_s(p->malloc_pool_, T_DATE);
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  yylval->node->is_copy_raw_text_ = 1;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
   return DATE_VALUE;
  }
}

Time{whitespace}?'[^']*' {
  ParseResult *p = (ParseResult *)yyextra;
  malloc_time_node_s(p->malloc_pool_, T_TIME);
  check_value(yylval);
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  yylval->node->is_copy_raw_text_ = 1;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return DATE_VALUE;
  }
}

Timestamp{whitespace}?'[^']*' {
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  malloc_time_node_s(p->malloc_pool_, T_TIMESTAMP);
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  yylval->node->is_copy_raw_text_ = 1;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return DATE_VALUE;
  }
}
Date{whitespace}?\"[^\"]*\" {
  ParseResult *p = (ParseResult *)yyextra;
  malloc_time_node_d(p->malloc_pool_, T_DATE);
  check_value(yylval);
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  yylval->node->is_copy_raw_text_ = 1;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return DATE_VALUE;
  }
}

Time{whitespace}?\"[^\"]*\" {
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  malloc_time_node_d(p->malloc_pool_, T_TIME);
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  yylval->node->is_copy_raw_text_ = 1;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return DATE_VALUE;
  }
}

Timestamp{whitespace}?\"[^\"]*\" {
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  malloc_time_node_d(p->malloc_pool_, T_TIMESTAMP);
  COPY_STRING(p->input_sql_ + yylloc->first_column - 1, yyleng, yylval->node->raw_text_);
  yylval->node->text_len_ = yyleng;
  yylval->node->is_copy_raw_text_ = 1;
  if (IS_FAST_PARAMETERIZE) {
    STORE_PARAM_NODE();
  } else {
    return DATE_VALUE;
  }
}

\/\*HINT\+[^*]+\*\/    {
  if (!(IS_FAST_PARAMETERIZE)) {
    int64_t out_len = 0;
    char *dest = NULL;
    check_value(yylval);
    /* ParseNode *node = new_node(((ParseResult *)yyextra)->malloc_pool_, T_HINT, 0); */
    ParseNode *node = NULL;
    ParseResult *p = (ParseResult *)yyextra;
    malloc_new_node(node, p->malloc_pool_, T_HINT, 0);
    dest = parse_strdup(yytext + 3, p->malloc_pool_, &out_len);
    check_value(dest);
    dest[out_len - 2] = '\0';

    node->str_value_ = dest;
    node->str_len_ = out_len - 1;

    yylval->node = node;
  }
  return HINT_VALUE;
}

{select_hint_begin} {
  BEGIN(hint);
  ParseResult *p = (ParseResult *)yyextra;
  p->is_ignore_token_ = p->is_ignore_hint_;
  return SELECT_HINT_BEGIN;
}

{update_hint_begin} {
  BEGIN(hint);
  ParseResult *p = (ParseResult *)yyextra;
  p->is_ignore_token_ = p->is_ignore_hint_;
  return UPDATE_HINT_BEGIN;
}
{delete_hint_begin} {
  BEGIN(hint);
  ParseResult *p = (ParseResult *)yyextra;
  p->is_ignore_token_ = p->is_ignore_hint_;
  return DELETE_HINT_BEGIN;
}
{insert_hint_begin} {
  BEGIN(hint);
  ParseResult *p = (ParseResult *)yyextra;
  p->is_ignore_token_ = p->is_ignore_hint_;
  return INSERT_HINT_BEGIN;
}
{replace_hint_begin} {
  BEGIN(hint);
  ParseResult *p = (ParseResult *)yyextra;
  p->is_ignore_token_ = p->is_ignore_hint_;
  return REPLACE_HINT_BEGIN;
}
{hint_hint_begin} {
  BEGIN(hint);
  ParseResult *p = (ParseResult *)yyextra;
  p->is_ignore_token_ = p->is_ignore_hint_;
  return HINT_HINT_BEGIN;
}
{load_data_hint_begin} {
  BEGIN(hint);
  ParseResult *p = (ParseResult *)yyextra;
  p->is_ignore_token_ = p->is_ignore_hint_;
  return LOAD_DATA_HINT_BEGIN;
}
<hint>{c_cmt_end} {
  BEGIN(INITIAL);
  return HINT_END;
}
<hint>[ \t\r\n] {
  ParseResult *p = (ParseResult *)yyextra;
  if (IS_FAST_PARAMETERIZE && !p->is_ignore_token_) {
    COPY_WRITE();
  }
}
<hint>INDEX { return INDEX_HINT; }
<hint>USE_NL { return USE_NL; }
<hint>NO_USE_NL { return NO_USE_NL; }
<hint>USE_BNL { return USE_BNL; }
<hint>NO_USE_BNL { return NO_USE_BNL; }
<hint>USE_NL_MATERIALIZATION { return USE_NL_MATERIALIZATION; }
<hint>NO_USE_NL_MATERIALIZATION { return NO_USE_NL_MATERIALIZATION; }
<hint>FROZEN_VERSION { return FROZEN_VERSION; }
<hint>TOPK { return TOPK; }
<hint>QUERY_TIMEOUT { return QUERY_TIMEOUT; }
<hint>READ_CONSISTENCY  { return READ_CONSISTENCY; }
<hint>WEAK  { return WEAK; }
<hint>STRONG  { return STRONG; }
<hint>FROZEN  { return FROZEN; }
<hint>NONE  { return NONE; }
<hint>DEFAULT  { return DEFAULT; }
<hint>MAX_CONCURRENT { return MAX_CONCURRENT; }
<hint>PARALLEL { return PARALLEL; }
<hint>NO_PARALLEL { return NO_PARALLEL; }
<hint>AUTO { return AUTO; }
<hint>FORCE { return FORCE; }
<hint>[(),.@]  {
  ParseResult *p = (ParseResult *)yyextra;
  if (!p->is_ignore_token_) {
    if (IS_FAST_PARAMETERIZE) {
      if (!p->is_ignore_token_) {
        COPY_WRITE();
      }
    } else {
      return yytext[0];
    }
  }
}
<hint>HOTSPOT  { return HOTSPOT; }
<hint>LOG_LEVEL  { return LOG_LEVEL; }
<hint>LEADING  { return LEADING_HINT; }
<hint>ORDERED  { return ORDERED; }
<hint>NO_REWRITE { return NO_REWRITE; }
<hint>FULL  { return FULL_HINT; }
<hint>USE_MERGE  { return USE_MERGE; }
<hint>NO_USE_MERGE  { return NO_USE_MERGE; }
<hint>USE_HASH  { return USE_HASH; }
<hint>NO_USE_HASH  { return NO_USE_HASH; }
<hint>USE_PLAN_CACHE  { return USE_PLAN_CACHE; }
<hint>USE_JIT { return USE_JIT; }
<hint>NO_USE_JIT { return NO_USE_JIT; }
<hint>USE_HASH_AGGREGATION  { return USE_HASH_AGGREGATION; }
<hint>NO_USE_HASH_AGGREGATION  { return NO_USE_HASH_AGGREGATION; }
<hint>USE_LATE_MATERIALIZATION  { return USE_LATE_MATERIALIZATION; }
<hint>NO_USE_LATE_MATERIALIZATION  { return NO_USE_LATE_MATERIALIZATION; }
<hint>TRACE_LOG { return TRACE_LOG; }
<hint>USE_PX { return USE_PX; }
<hint>LOAD_BATCH_SIZE { return LOAD_BATCH_SIZE; }
<hint>TRACING { return TRACING; }
<hint>FORCE_REFRESH_LOCATION_CACHE { return FORCE_REFRESH_LOCATION_CACHE; }
<hint>STAT { return STAT; }
<hint>NO_USE_PX { return NO_USE_PX; }
<hint>PX_JOIN_FILTER { return PX_JOIN_FILTER; }
<hint>NO_PX_JOIN_FILTER { return NO_PX_JOIN_FILTER; }
<hint>QB_NAME { return QB_NAME; }
<hint>TRANS_PARAM { return TRANS_PARAM; }
<hint>PQ_DISTRIBUTE { return PQ_DISTRIBUTE; }
<hint>PQ_MAP { return PQ_MAP; }
<hint>PRANDOM_LOCAL { return RANDOM_LOCAL; }
<hint>BROADCAST { return BROADCAST; }
<hint>PARTITION { return PARTITION; }
<hint>HASH { return HASH; }
<hint>[-] { return NEG_SIGN; }
<hint>MERGE { return MERGE_HINT; }
<hint>NO_MERGE { return NO_MERGE_HINT; }
<hint>NO_EXPAND { return NO_EXPAND; }
<hint>USE_CONCAT { return USE_CONCAT; }
<hint>UNNEST { return UNNEST; }
<hint>NO_UNNEST { return NO_UNNEST; }
<hint>PLACE_GROUP_BY { return PLACE_GROUP_BY; }
<hint>NO_PLACE_GROUP_BY { return NO_PLACE_GROUP_BY; }
<hint>NO_PRED_DEDUCE { return NO_PRED_DEDUCE; }
<hint>ENABLE_PARALLEL_DML  { return ENABLE_PARALLEL_DML; }
<hint>DISABLE_PARALLEL_DML  { return DISABLE_PARALLEL_DML; }
<hint>{identifier} {
  if (!(IS_FAST_PARAMETERIZE)) {
    check_value(yylval);
    ParseResult *p = (ParseResult *)yyextra;
    ParseNode *node = NULL;
    malloc_new_node(node, p->malloc_pool_, T_IDENT, 0);
    yylval->node = node;
    int64_t out_len = 0;
    char *dup_value = NULL;
    if (p->is_not_utf8_connection_) {
      dup_value = parse_str_convert_utf8(p->charset_info_, yytext, p->malloc_pool_, &out_len, &(p->extra_errno_));
      check_identifier_convert_result(p->extra_errno_);
    } else {
      dup_value = parse_strdup(yytext, p->malloc_pool_, &out_len);
    }
    check_value(dup_value);
    node->str_value_ = str_tolower(dup_value, strlen(dup_value));
    node->str_len_ = out_len;
    setup_token_pos_info(node, yylloc->first_column - 1, yylval->node->str_len_);
  }
  return NAME_OB;
}

<hint>{quote}  {
  ParseResult *p = (ParseResult *)yyextra;
  if (!p->is_ignore_token_) {
    BEGIN(log_level);
    if (IS_FAST_PARAMETERIZE) {
      COPY_WRITE();
    } else {
      return yytext[0];
    }
  }
}

{c_cmt_begin} {
BEGIN(in_c_comment);
#ifdef SQL_PARSER_COMPILATION
  ParseResult *p = (ParseResult *)yyextra;
  if (false == p->stop_add_comment_) {
    TokenPosInfo info;
    info.token_off_ = yylloc->first_column - 1;
    info.token_len_ = -1;
    if (OB_UNLIKELY(OB_PARSER_SUCCESS != add_comment_list(p, &info))) {
      YY_FATAL_ERROR("add comment to comment list failed");
    }
  }
#endif
}

<in_c_comment>{c_cmt_end} {
  ((ParseResult *)yyextra)->has_encount_comment_ = true;
  BEGIN(INITIAL);
#ifdef SQL_PARSER_COMPILATION
  ParseResult *p = (ParseResult *)yyextra;
  p->has_encount_comment_ = true;
  if (false == p->stop_add_comment_) {
    if (OB_UNLIKELY(0 >= p->comment_cnt_)) {
      YY_FATAL_ERROR("comment_cnt_ cannot less than 0 in comment end");
    } else {
      TokenPosInfo *info = &(p->comment_list_[p->comment_cnt_-1]);
      info->token_len_ = yylloc->last_column - info->token_off_;
    }
  }
#endif
}

<in_c_comment><<EOF>>  {
  yyerror(yylloc, yyextra, "unterminated log_level string\n");
  return PARSER_SYNTAX_ERROR;
}
<in_c_comment>[\n] { yylineno++; }
<in_c_comment>. {}

<log_level>{log_level_stmt} {
  if (IS_FAST_PARAMETERIZE) {
    COPY_WRITE();
  } else {
    check_value(yylval);
    ParseNode *node = NULL;
    ParseResult *p = (ParseResult *)yyextra;
    malloc_new_node(node, p->malloc_pool_, T_LOG_LEVEL, 0);
    yylval->node = node;
    char *dup_value = NULL;
    int64_t out_len = 0;
    dup_value = parse_strdup(yytext, p->malloc_pool_, &out_len);
    check_value(dup_value);
    node->str_value_ = str_tolower(dup_value, strlen(dup_value));
    node->str_len_ = out_len;
    return STRING_VALUE;
  }
}

<log_level>{quote}  {
  BEGIN(hint);
  if (IS_FAST_PARAMETERIZE) {
    COPY_WRITE();
  } else {
    return yytext[0];
  }
}

<log_level><<EOF>>  {
  yyerror(yylloc, yyextra, "unterminated log_level string\n");
  return PARSER_SYNTAX_ERROR;
}

<log_level>. {}

<hint><<EOF>>  {
  yyerror(yylloc, yyextra, "unterminated hint string\n");
  return PARSER_SYNTAX_ERROR;
}
<hint>. {}

{comment} {
  ((ParseResult *)yyextra)->has_encount_comment_ = true;
/* ignore */ }

[-+&~|^/%*(),.:!] {
  if (IS_FAST_PARAMETERIZE) {
    ParseResult *p = (ParseResult *)yyextra;
    // for 'select -   -1 from dual'
    // the first neg sign is not copied when it is parsed
    // but when the second neg sign is parsed, the first neg sign must be put where is should be
    if ('-' == yytext[0]) {
      REPUT_NEG_SIGN(p);
      p->minus_ctx_.pos_ = p->no_param_sql_len_;
      p->minus_ctx_.raw_sql_offset_ = yylloc->first_column - 1;
      p->minus_ctx_.has_minus_ = true;
    } else {
      COPY_WRITE();
      REPUT_NEG_SIGN(p);
    }
  } else {
    return yytext[0];
  }
}

[;] {
  if (IS_FAST_PARAMETERIZE) {
    ParseResult *p = (ParseResult *)yyextra;
    if (p->is_batched_multi_enabled_split_) {
      RM_MULTI_STMT_END_P(p);
    } else {
      COPY_WRITE();
    }
    return END_P;
  } else {
    return DELIMITER;
  }
}

"||" {
  int ret = CNNOP; /*fast parameterize don't care CNNOP or OR_OP*/
  if (!(IS_FAST_PARAMETERIZE)) {
    ObSQLMode mode = ((ParseResult *)yyextra)->sql_mode_;
    bool is_pipes_as_concat = false;
      IS_PIPES_AS_CONCAT(mode, is_pipes_as_concat);
    if (is_pipes_as_concat) {
      ret = CNNOP;
    } else {
      ret = OR_OP;
    }
  }
  return ret;
}

"&&" {return AND_OP;}
"="  {return COMP_EQ;}
":="  {return SET_VAR;}
"<=>"  {return COMP_NSEQ;}
">=" {return COMP_GE;}
">"  {return COMP_GT;}
"<=" {return COMP_LE;}
"<"  {return COMP_LT;}
"!="|"<>" {return COMP_NE;}
"<<"  {return SHIFT_LEFT;}
">>"  {return SHIFT_RIGHT;}

"?" {
  //use for outline now, means any value
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  malloc_new_node(yylval->node, p->malloc_pool_, T_QUESTIONMARK, 0);
  yylval->node->value_ = p->question_mark_ctx_.count_++;
  p->question_mark_ctx_.by_ordinal_ = true;
  if (OB_UNLIKELY(p->question_mark_ctx_.by_name_)) {
    YY_FATAL_ERROR("Ordinal binding and Named binding cannot be combined\n");
  }
  if (IS_FAST_PARAMETERIZE) {
    yylval->node->raw_text_ = parse_strdup(yytext, p->malloc_pool_, &(yylval->node->text_len_));
    check_value(yylval->node->raw_text_);
    STORE_PARAM_NODE();
  } else {
    return QUESTIONMARK;
  }
}

":"{int_num} {
  ParseResult *p = (ParseResult *)yyextra;
  check_value(yylval);
  malloc_new_node(yylval->node, p->malloc_pool_, T_QUESTIONMARK, 0);
  yylval->node->value_ = get_question_mark(&p->question_mark_ctx_, p->malloc_pool_, yytext);
  if (IS_FAST_PARAMETERIZE) {
    yylval->node->raw_text_ = parse_strdup(yytext, p->malloc_pool_, &(yylval->node->text_len_));
    check_value(yylval->node->raw_text_);
    STORE_PARAM_NODE();
  } else {
    return QUESTIONMARK;
  }
}

{system_variable} {
  if (!(IS_FAST_PARAMETERIZE)) {
    /* ParseNode *node = new_node(((ParseResult *)yyextra)->malloc_pool_, T_SYSTEM_VARIABLE, 0); */
    ParseNode *node = NULL;
    ParseResult *p = (ParseResult *)yyextra;
    check_value(yylval);
    malloc_new_node(node, p->malloc_pool_, T_SYSTEM_VARIABLE, 0);
    yylval->node = node;
    /* skip '@@' */
    node->str_value_ = parse_strdup(yytext + 2, p->malloc_pool_, &(node->str_len_));
    check_value(node->str_value_);
    //node->value_ = 2;
    node->value_ = 0;
  } else {
    ParseResult *p = (ParseResult *)yyextra;
    REPUT_NEG_SIGN(p);
  }
  return SYSTEM_VARIABLE;
}

{user_variable} {
  /* ParseNode *node = new_node(p->malloc_pool_, T_TEMP_VARIABLE, 0); */
  if (!(IS_FAST_PARAMETERIZE)) {
    ParseNode *node = NULL;
    ParseResult *p = (ParseResult *)yyextra;
    check_value(yylval);
    malloc_new_node(node, p->malloc_pool_, T_USER_VARIABLE_IDENTIFIER, 0);
    yylval->node = node;
    /* skip '@' and quotes like '/"/` */
    node->str_value_ = parse_strdup(yytext + 1, p->malloc_pool_, &(node->str_len_));
    if (NULL != node->str_value_
    		&& *(yytext + 1) == *(yytext + node->str_len_)
    		&& (*(yytext + 1) == '\'' || *(yytext + 1) == '\"' || *(yytext + 1) == '`')) {
			node->str_value_ += 1;
			node->str_len_ -= 2;
		}
    check_value(node->str_value_);
  } else {
    ParseResult *p = (ParseResult *)yyextra;
    REPUT_NEG_SIGN(p);
  }
  return USER_VARIABLE;
}

{identifier} {
  const NonReservedKeyword *word = NULL;
  if (IS_FAST_PARAMETERIZE) {
    ParseResult *p = (ParseResult *)yyextra;
    REPUT_NEG_SIGN(p);
    if (strcasecmp("nowait", yytext) == 0
        || strcasecmp("no_wait", yytext) == 0) {
      char num[2] = "0";
      STORE_UNIT_TYPE_NODE(num);
    } else {
      return NAME_OB;
    }
  } else {
    int ret = NAME_OB;
    if (NULL == (word = mysql_non_reserved_keyword_lookup(yytext)))
    {
      check_value(yylval);
      ParseNode *node = NULL;
      ParseResult *p = (ParseResult *)yyextra;
      malloc_new_node(node, p->malloc_pool_, T_IDENT, 0);
      yylval->node = node;
      if (p->is_not_utf8_connection_) {
        node->str_value_ = parse_str_convert_utf8(p->charset_info_, yytext, p->malloc_pool_, &(node->str_len_), &(p->extra_errno_));
        check_identifier_convert_result(p->extra_errno_);
        //fprintf(stderr, "parse identifier result, str=%s, str_len=%ld\n", node->str_value_, node->str_len_);
      } else {
        node->str_value_ = parse_strdup(yytext, p->malloc_pool_, &(node->str_len_));
      }
      check_value(node->str_value_);
      setup_token_pos_info(node, yylloc->first_column - 1, node->str_len_);
      ret = NAME_OB;
      //CHECK_NODE_STRING_VALUE_ASCII(ret, node->str_value_, node->str_len_);
    } else {
      yylval->non_reserved_keyword = word;
      ret = word->keyword_type;
    }
    return ret;
  }
}

[\n] {
  yylineno ++;
  if (IS_FAST_PARAMETERIZE) {
    COPY_WRITE();
  }
}

[ \t\r] {
  if (IS_FAST_PARAMETERIZE) {
    COPY_WRITE();
  }
}
"--"[ \t].*;

<<EOF>> {return END_P;}
. {
  ParseResult *p = (ParseResult *)yyextra;
  if (p->input_sql_len_ == yylloc->first_column) {
    return END_P;
  } else {
    yyerror(yylloc, yyextra, "mystery charactor '%c'\n", *yytext);
    return PARSER_SYNTAX_ERROR;
  }
}
%%

void *yyalloc(size_t bytes, void *yyscanner)
{
  void *ptr_ret = NULL;
  ParseResult *p = yyget_extra(yyscanner);
  if (OB_UNLIKELY(NULL == p)) {
  } else {
    ptr_ret = parse_malloc(bytes, p->malloc_pool_);
  }
  return ptr_ret;
}

void *yyrealloc(void *ptr, size_t bytes, void *yyscanner)
{
  void *ptr_ret = NULL;
  ParseResult *p = yyget_extra(yyscanner);
  if (OB_UNLIKELY(NULL == p)) {
  } else {
    ptr_ret = parse_realloc(ptr, bytes, p->malloc_pool_);
  }
  return ptr_ret;
}

void yyfree(void *ptr, void *yyscanner)
{
  UNUSED(yyscanner);
  /* Do nothing -- we leave it to the garbage collector. */
  parse_free(ptr);
}
